namespace Crux.Core.LangChain.OpenAI;
/// <summary>
/// 
/// </summary>
public class OpenAIEmbeddingGenerationService(OpenAIOption option) : ITextEmbeddingGenerationService
{
    private readonly OpenAIOption _option = option
            ?? throw new ArgumentNullException(nameof(option));
    /// <summary>
    /// 
    /// </summary>
    /// <param name="data"></param>
    /// <param name="dimensions"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public async Task<float[]> GenerateEmbeddingAsync(
        string data,
        int dimensions = 1536,
        CancellationToken cancellationToken = default)
    {
        var client = GetEmbeddingClient();

        var embedding = await client.GenerateEmbeddingAsync(
            data,
            new EmbeddingGenerationOptions
            {
                Dimensions = dimensions
            },
            cancellationToken: cancellationToken).ConfigureAwait(false);

        return embedding.Value?.ToFloats().ToArray() ?? Array.Empty<float>();
    }

    private EmbeddingClient GetEmbeddingClient()
    {
        var option = new OpenAIClientOptions
        {
            Endpoint = _option.Endpoint
        };

        var credential = new ApiKeyCredential(_option.ApiKey);

        var client = new EmbeddingClient(
            model: _option.Model,
            credential,
            option);

        return client;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="data"></param>
    /// <param name="dimensions"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception> 
    public async Task<IList<float[]>> GenerateEmbeddingsAsync(
        IList<string> data,
        int dimensions = 1536,
        CancellationToken cancellationToken = default)
    {
        var client = GetEmbeddingClient();

        var embeddings = await client.GenerateEmbeddingsAsync(
            data,
            new EmbeddingGenerationOptions
            {
                Dimensions = dimensions
            },
            cancellationToken: cancellationToken).ConfigureAwait(false);

        return embeddings.Value?.Select(e => e.ToFloats().ToArray()).ToArray() ?? Array.Empty<float[]>();
    }
}